package com.ys.多线程.p3线程同步;

/**
 * 描述:SynchronizerInDepth 的深入了解
 * 一:
 *  * synchronize -- 加锁,
 *  *  可以修饰方法  - 静态与成员
 *  *  可以修饰代码块 - synchronize(this){}
 *  *  可以修饰当前对象的某一个属性,--必须是引用类型
 *  *  看到这个是一个this,this本质是一个引用指针,所以是一个引用类型地址值
 *  *  所以可以去锁自定义的类,以及各种包装类修饰的变量
 *  *  注意:
 *  *  如果锁是当前对象的一个属性，最好使用final修饰，让其不可变
 *  *  使用synchronize加锁的原则：让你的锁足够的轻、小
 *  *  二:
 *  *    使用synchronizer 修饰的 同步代码块,或者 方法, 当进入该线程"内容执行时" 其他线程就会被 MONTIOR == 监控,管程,管住
 *  *  三:
 *  *  同步方法对应的字节码指令如下：
 *  *
 *  *  ACC_SYNCHRONIZED 同步方法对应的字节码指令
 *  *  monitorenter、monitorexit 同步块对应的字节码指令
 *
 *  四:
 *  小结：同步块不用锁住整个方法，只用锁住某一段代码，所以同步块效率比同步方法高
 * ​	   synchronized是JVM级别的锁，程序运行时JVM帮我们加锁和解锁，我们无法控制。缺点：在低版本的JDK中synchronized会“卡死”
 *五:
 * 总结1：synchronized关键字使用注意点
 * 1、只能同步方法和代码块，而不能同步变量和类。
 * 2、只有共享资源的读写访问才需要同步，如果不是共享资源，根本没有同步的必要。
 * 3、编写线程安全的代码会使系统的总体效率会降低，并且容易发生死锁的情况。
 * 4、无论是同步代码块还是同步方法，必须获得对象锁才能够进入同步代码块或同步方法进行操作。
 * 5、如果是非静态同步方法，对象锁为方法所在的对象；如果是静态同步方法，对象锁为方法所在的类（唯一）。
 * 6、如果两个线程要执行一个类中的静态同步方法或非静态同步方法，那么一次只能有一个线程能够执行方法，另一个需要等待，直到锁被释放。也就是说，如果一个线程在对象上获得一个锁，就没有任何其它线程可以进入（该对象的）类中的任何一个同步方法。
 *
 * 六:总结2：一个线程取得了同步锁，那么在什么时候才会释放掉呢？
 * 1、同步方法或代码块正常结束。
 * 2、使用return或 break终止了执行，或者抛出了未处理的异常。
 * 3、当线程执行同步方法或代码块时，程序执行了同步锁对象的wait()方法。
 * 七:
 * 总结3：synchronized的可重入性
 * 在使用synchronized时，当一个线程得到一个对象锁后（只要该线程还没有释放这个对象锁），
 * 再次请求此对象锁时是可以再次得到该对象的锁的（例如：同步方法可以调用同一个对象的另一个同步方法）。
 *
 * @author CodeYang
 * @version 2021/1/5 19:51
 */
public class SynchronizerInDepth {

    /**
     * javac 编译
     * java 执行
     * javap 反编译
     *  使用反编译命令: javap -c -l -v 类名.class   -c返回字节码 -l显示行号 -v显示变量
     *  我这里使用了中文无法之间编译:可以到外面去开辟新文件使用
     */

    /**
     * 同步方法-锁方法 对应的字节码指令 ACC_SYNCHRONIZED  要用public反编译后才可以看到
     */
    public synchronized void  function01(){

    }


    public void function(){
        //同步块对应的字节码指令 monitorenter 进入监视区、monitorexit退出临界区 ,monitorexit, 两个退出
        synchronized (this){

        }
    }


}
